<?php
namespace Forxx;
use Lavender\Errno;
use Lavender\Filter;
use Lavender\Exception;
use Forxx\Signature;
use Forxx\ErrnoPlus;
use Lavender\Core;

class ServerService extends \Lavender\WebService
{

	protected $communicate_id = '';
	private $system_sign;

	public function before_execute()
	{
		$route_options = self::get_route_options();
		$action_name = $route_options['action'];
		if (
			!empty($this->without_auth_actions) &&
			(array_search($action_name, $this->without_auth_actions) !== false || array_search('*', $this->without_auth_actions) !== false)
		) {
			return;
		}

		//必须参数
		$param_req = array(
			'communicate_id' => Filter::T_STRING,   //应用id
			'version' => Filter::T_STRING,  //版本号
			'sign' => Filter::T_STRING, //签名
		);
		$param = $this->parameters($param_req, self::M_GET, true);

		$communicate_key = Core::get_config('const', $param['communicate_id']);

		//获取请求参数
		$request = $this->get_request_param();
		//验证签名是否正确
		if(!$this->is_valid_signature($communicate_key, $request, $param['sign'])){
			throw new Exception('sign invalid', ErrnoPlus::PARAM_INVALID);
		}

		$this->communicate_id = $param['communicate_id'];

	}

	/**
	 * 验证签名是否正确
	 * @param string $request_param
	 * @param string $sign
	 * @return boolean
	 */
	private function is_valid_signature($key, $request_param, $signature)
	{
		//根据提交的参数获取计算出来的签名
		$signature_obj = new Signature($key, '', array('sign' => 1));
		$this->system_sign = $signature_obj->get_signature($request_param);

		if ($signature == $this->system_sign) {
			return true;
		}

		return false;
	}

	private function get_request_param()
	{
		$request = array();
		if (!empty($_GET)) {
			foreach ($_GET as $key => $value) {
				$request[$key] = $value;
			}
		}
		if (!empty($_POST)) {
			foreach ($_POST as $key => $value) {
				$request[$key] = $value;
			}
		}
		return $request;
	}
	
	public function execute($action_name)
	{
		$this->header_content_type(static::CONTENT_TYPE);

		try {
			$this->before_execute();
			$this->action_name = $action_name;
			$action_method = "{$action_name}_action";

			//action not found
			if (!method_exists($this, $action_method)) {
					$this->header_notfound();
					return ;
			}

			//call action
			$data = $this->$action_method();

			//render
			return $this->render($data);
		}
		catch (Exception $e) {
			return $this->render_error($e->getMessage(), $e->getCode());
		}
	}

	public function render($__data__ = null, $__view__ = null)
	{
		//get friend message
		if (isset($__data__['code']) && $__data__['code'] > 0) {
			//debug on error
			if (L_DEBUG) {
				$__data__['debug_msg'] = $__data__['msg'];
			}

			$__data__['msg'] = \Lavender\Core::get_lang_text($__data__['code']);
		}

		//json
		$response = json_encode($__data__, JSON_UNESCAPED_UNICODE);

		echo $response;

		//write session flow
		$this->session_flow($__data__);
	}

	public function log($contents, $log_name = 'debug')
	{
		$old_mask = umask(0);

		//check & make dir
		$dir = L_WORKSPACE_PATH . 'log/' . L_APP_NAME . '/';
		if (!is_dir($dir)) {
			mkdir($dir, 0777, true);
		}

		//write file
		$file = $dir . $log_name;
		file_put_contents($file . '.log', $contents, FILE_APPEND | LOCK_EX);

		//keep small than 1G
		if (filesize($file . '.log') > 1000000000) {
			rename($file . '.log', $file . '.' . date('His') . '.log');
		}

		umask($old_mask);

	}
}
